# coding: utf-8

import json
import sys
from enum import Enum

import pandas as pd
from PySide6.QtCharts import QChart, QChartView, QLineSeries, QDateTimeAxis, QValueAxis
from PySide6.QtCore import Qt, QPoint, QRect, QDateTime, QDate, QTime, QTimer
from PySide6.QtGui import QMouseEvent
from PySide6.QtWidgets import QApplication, QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QLabel, QSizePolicy, \
    QTableView, QLineEdit, QAbstractItemView

import resourse  # type: ignore
from dataModel import ETFModel, HistModel


class Location(Enum):
    TOP = 1
    BOTTOM = 2
    LEFT = 3
    RIGHT = 4
    TOP_LEFT = 5
    TOP_RIGHT = 6
    BOTTOM_LEFT = 7
    BOTTOM_RIGHT = 8
    CENTER = 9


PADDING = 5


class MainWidgets(QWidget):
    def __init__(self):
        super().__init__()
        self.model = ETFModel()
        self.histModel = HistModel("")
        self.initUI()
        self.leftPressed = False
        self.mouseOffset = None
        self.location = None
        self.code = None   # 当前ETF代码

        # 初始化数据模型金额
        self.onBtnMoneyClicked()

    def initUI(self):
        self.setMinimumSize(800, 450)
        self.setWindowFlag(Qt.WindowType.FramelessWindowHint)
        self.setWindowState(self.windowState() | Qt.WindowState.WindowMaximized)

        # 设置窗口标题栏
        self.fr_bar = QWidget()
        self.setBarUI(self.fr_bar)

        self.wdg_content = QWidget()
        self.setContent(self.wdg_content)

        hbl_main = QVBoxLayout()
        hbl_main.setContentsMargins(0, 0, 0, 0)
        hbl_main.addWidget(self.fr_bar)
        hbl_main.addWidget(self.wdg_content)

        with open('style.qss') as f:
            style = f.read()
        self.setStyleSheet(style)
        self.setLayout(hbl_main)

        # self.setMouseTracking(True)  # 开启鼠标追踪
        # self.fr_bar.setMouseTracking(True)
        # self.installEventFilter(self.fr_bar)
        # self.wdg_content.setMouseTracking(True)
        # self.installEventFilter(self.wdg_content)

        # self.timer = QTimer(self)
        # self.timer.timeout.connect(self.onTimer)
        # self.timer.start(1000)

    def setBarUI(self, frame: QWidget):
        """设置标题栏"""
        hbl_bar = QHBoxLayout()
        hbl_bar.setContentsMargins(0, 0, 0, 0)

        lbl_icon = QLabel()
        lbl_icon.setFixedSize(32, 32)
        lbl_title = QLabel("基金投资小工具")
        lbl_title.setMinimumWidth(60)
        sizePolicy = QSizePolicy(QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Fixed)
        lbl_title.setSizePolicy(sizePolicy)

        # 右上角
        wdg_btn = QWidget()
        self.setBarTopRight(wdg_btn)

        hbl_bar.addWidget(lbl_icon)
        hbl_bar.addWidget(lbl_title)
        hbl_bar.addWidget(wdg_btn)
        frame.setFixedHeight(40)
        frame.setSizePolicy(QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Fixed)
        frame.setLayout(hbl_bar)
        frame.setObjectName("wdg_bar")

    def setContent(self, frame: QWidget):

        wdg_up = QWidget()
        self.setWdgUP(wdg_up)

        self.charView = QChartView()
        self.charView.setMinimumHeight(600)
        self.charView.hide()

        vbl_content = QVBoxLayout()
        vbl_content.addWidget(wdg_up)
        vbl_content.addWidget(self.charView)
        frame.setLayout(vbl_content)

    def setWdgUP(self, frame: QWidget):
        table = QTableView()
        table.setModel(self.model)
        table.setSortingEnabled(True)
        table.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows)
        table.verticalHeader().hide()
        table.doubleClicked.connect(self.onTableDoubleClick)

        self.ldt_money = QLineEdit()
        self.ldt_money.setText("2000")
        self.btn_money = QPushButton("资金")
        self.btn_fresh = QPushButton("刷新")
        vbl_right = QVBoxLayout()
        vbl_right.setContentsMargins(0, 0, 0, 0)
        vbl_right.addWidget(self.ldt_money)
        vbl_right.addWidget(self.btn_money)
        vbl_right.addWidget(self.btn_fresh)

        wdg_right = QWidget()
        wdg_right.setMinimumWidth(20)
        wdg_right.setSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Preferred)
        wdg_right.setLayout(vbl_right)

        # 历史数据
        self.tb_hist = QTableView()
        self.tb_hist.setMaximumWidth(400)
        self.tb_hist.setModel(self.histModel)
        self.tb_hist.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows)
        self.tb_hist.verticalHeader().hide()

        hbl_up = QHBoxLayout()
        hbl_up.setSpacing(20)
        hbl_up.addWidget(table)
        hbl_up.addWidget(wdg_right)
        hbl_up.addWidget(self.tb_hist)

        frame.setLayout(hbl_up)

        self.btn_fresh.clicked.connect(self.onBtnFreshClicked)
        self.btn_money.clicked.connect(self.onBtnMoneyClicked)

    def onTableDoubleClick(self, index):
        code, name, net_date = self.model.get_code_info(index)
        if code is None:
            self.charView.hide()
            return

        chart = QChart()
        chart.setTitle("{code} {name}走势图".format(code=code, name=name))

        line_value = QLineSeries()
        line_fast = QLineSeries()
        line_value.setName("净值")
        line_fast.setName("KAMA(11)")

        chart.addSeries(line_value)
        chart.addSeries(line_fast)

        with open("data/fund/{code}.json".format(code=code), "r", encoding="utf-8") as f:
            etf_data = json.load(f)
        for one in etf_data:
            xValue = QDateTime()
            qDate = self.strDate2QDate(one["trade_date"])
            xValue.setDate(qDate)
            xValue.setTime(QTime(0, 0, 0))

            line_value.append(xValue.toMSecsSinceEpoch(), one["unit_worth"])
            if one["kama"] is not None:
                line_fast.append(xValue.toMSecsSinceEpoch(), one["kama"])

        df_etf = pd.DataFrame(etf_data)
        df_etf = df_etf.tail(250)

        axisX = QDateTimeAxis()
        axisX.setFormat("yyyy-MM-dd")
        one = df_etf.iloc[0]
        start = self.strDate2QDate(one["trade_date"])
        one = df_etf.iloc[-1]
        end = self.strDate2QDate(one["trade_date"])
        axisX.setRange(QDateTime(start,QTime(0,0,0)), QDateTime(end,QTime(0,0,0)))
        axisX.setTickCount(20)
        axisX.setTitleText("日期")

        axisY = QValueAxis()
        minY = df_etf["unit_worth"].min()
        minY = minY - (minY * 0.05)
        maxY = df_etf["unit_worth"].max()
        maxY = maxY + (maxY * 0.05)
        axisY.setRange(minY, maxY)
        axisY.setTickCount(8)
        axisY.setLabelFormat("%0.4f")
        chart.addAxis(axisX, Qt.AlignmentFlag.AlignBottom)
        chart.addAxis(axisY, Qt.AlignmentFlag.AlignLeft)
        line_value.attachAxis(axisX)
        line_value.attachAxis(axisY)
        line_fast.attachAxis(axisX)
        line_fast.attachAxis(axisY)

        self.charView.setChart(chart)
        self.charView.show()

        self.tb_hist.scrollToTop()
        self.histModel.change_data(code)

    def strDate2QDate(self, strDate)->QDate:
        year = strDate[0:4]
        month = strDate[4:6]
        day = strDate[6:8]
        return QDate(int(year), int(month), int(day))

    def onBtnFreshClicked(self):
        self.model.refresh()

    def onBtnMoneyClicked(self):
        self.model.setMoney(float(self.ldt_money.text()))

    def mousePressEvent(self, a0: QMouseEvent):
        super().mousePressEvent(a0)
        # if a0.button() == Qt.MouseButton.LeftButton:
        #     a0.accept()
        #     self.leftPressed = True
        #     self.mouseOffset = a0.globalPosition().toPoint() - self.frameGeometry().topLeft()

    def mouseDoubleClickEvent(self, event: QMouseEvent):
        super().mouseDoubleClickEvent(event)
        position = event.position().toPoint()
        if self.isMouseInBar(position):
            self.onMaxRestore()

    def isMouseInBar(self, position: QPoint):
        return (self.fr_bar.x() <= position.x() <= self.fr_bar.x() + self.fr_bar.width()
                and self.fr_bar.y() <= position.y() <= self.fr_bar.y() + self.fr_bar.height())

    def mouseReleaseEvent(self, event: QMouseEvent):
        super().mouseReleaseEvent(event)
        # if event.button() == Qt.MouseButton.LeftButton:
        #     event.accept()
        #     self.leftPressed = False
        #     self.shaping = False

    def mouseMoveEvent(self, event: QMouseEvent):
        super().mouseMoveEvent(event)
        # position = event.globalPosition().toPoint()
        # if not self.leftPressed:  # 左键未按下
        #     event.accept()
        #     self.setCursorShape(position)
        #     return
        #
        # # 移动窗口
        # if self.leftPressed:  # 左键按下
        #     pos = event.position().toPoint()
        #     if self.isMouseInBar(pos) and self.cursor().shape() == Qt.CursorShape.ArrowCursor:  # 鼠标是正常状态（比如在上边缘缩放窗口时，光标为其他）
        #         event.accept()
        #         self.move(position - self.mouseOffset)  # 更改窗口位置
        #         return
        #
        #     # 窗口缩放
        #     self.shapeWindow(position)
        #     event.accept()

    def eventFilter(self, a0, event: QMouseEvent):
        # if (a0 == self.fr_bar or a0 == self.wdg_content) \
        #         and not self.leftPressed and event.Type.MouseMove:
        #     event.accept()
        #     position = event.globalPosition().toPoint()
        #     self.setCursorShape(position)

        return super().eventFilter(a0, event)

    def shapeWindow(self, position: QPoint):
        rect = self.rect()
        topLeft = self.mapToGlobal(rect.topLeft())
        bottomRight = self.mapToGlobal(rect.bottomRight())
        move = QRect(topLeft, bottomRight)
        if self.location == Location.TOP \
                and bottomRight.y() - position.y() > self.minimumHeight():  # 如果不加此判断，窗口会被向下推走
            move.setY(position.y())
        elif self.location == Location.BOTTOM:
            move.setHeight(position.y() - topLeft.y())
        elif self.location == Location.LEFT \
                and bottomRight.x() - position.x() > self.minimumWidth():  # 防止窗口被推走
            move.setX(position.x())
        elif self.location == Location.RIGHT:
            move.setWidth(position.x() - topLeft.x())
        elif self.location == Location.TOP_LEFT:
            if bottomRight.y() - position.y() > self.minimumHeight():
                move.setY(position.y())
            if bottomRight.x() - position.x() > self.minimumWidth():
                move.setX(position.x())
        elif self.location == Location.TOP_RIGHT:
            if bottomRight.y() - position.y() > self.minimumHeight():
                move.setY(position.y())
            move.setWidth(position.x() - topLeft.x())
        elif self.location == Location.BOTTOM_LEFT:
            if bottomRight.x() - topLeft.x() > self.minimumWidth():
                move.setX(position.x())
            move.setHeight(position.y() - topLeft.y())
        elif self.location == Location.BOTTOM_RIGHT:
            move.setHeight(position.y() - topLeft.y())
            move.setWidth(position.x() - topLeft.x())
        self.setGeometry(move)

    def setCursorShape(self, position: QPoint):
        rect = self.rect()
        topLeft = self.mapToGlobal(rect.topLeft())
        bottomRight = self.mapToGlobal(rect.bottomRight())

        x = position.x()
        y = position.y()

        if (topLeft.x() <= x <= topLeft.x() + PADDING and  # 左上角
                topLeft.y() <= y <= topLeft.y() + PADDING):
            self.location = Location.TOP_LEFT
            self.setCursor(Qt.CursorShape.SizeFDiagCursor)

        elif (topLeft.x() <= x <= topLeft.x() + PADDING and  # 左下角
              bottomRight.y() - PADDING <= y <= bottomRight.y()):
            self.location = Location.BOTTOM_LEFT
            self.setCursor(Qt.CursorShape.SizeBDiagCursor)
        elif (bottomRight.x() - PADDING <= x <= bottomRight.x() and  # 右下角
              bottomRight.y() - PADDING <= y <= bottomRight.y()):
            self.location = Location.BOTTOM_RIGHT
            self.setCursor(Qt.CursorShape.SizeFDiagCursor)
        elif (bottomRight.x() - PADDING <= x <= bottomRight.x() and  # 右上角
              topLeft.y() <= y <= topLeft.y() + PADDING):
            self.location = Location.TOP_RIGHT
            self.setCursor(Qt.CursorShape.SizeBDiagCursor)
        elif topLeft.x() <= x <= topLeft.x() + PADDING:  # 左边
            self.location = Location.LEFT
            self.setCursor(Qt.CursorShape.SizeHorCursor)
        elif bottomRight.y() - PADDING <= y <= bottomRight.y():  # 下边
            self.location = Location.BOTTOM
            self.setCursor(Qt.CursorShape.SizeVerCursor)
        elif bottomRight.x() - PADDING <= x <= bottomRight.x():  # 右边
            self.location = Location.RIGHT
            self.setCursor(Qt.CursorShape.SizeHorCursor)
        elif topLeft.y() <= y <= topLeft.y() + PADDING:
            self.location = Location.TOP
            self.setCursor(Qt.CursorShape.SizeVerCursor)
        else:
            self.location = Location.CENTER
            self.setCursor(Qt.CursorShape.ArrowCursor)

    def setBarTopRight(self, frame: QWidget):
        """设置标题栏右边"""
        frame.setObjectName("fr_btn")
        frame.setFixedWidth(135)
        frame.setSizePolicy(QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Preferred)
        hbl_btn = QHBoxLayout()
        hbl_btn.setContentsMargins(0, 0, 0, 0)
        hbl_btn.setSpacing(0)
        self.btn_min = QPushButton()
        self.btn_min.setToolTip("最小化")
        self.setSVG(":images/min.svg", self.btn_min)
        self.btn_max = QPushButton()
        self.btn_max.setToolTip("最大化")
        self.btn_max.setDisabled(True)
        self.setSVG(":images/max.svg", self.btn_max)
        self.btn_close = QPushButton()
        self.btn_close.setObjectName("btn_close")
        self.btn_close.setToolTip("关闭")
        self.setSVG(":images/close.svg", self.btn_close)
        ls_btn = [self.btn_min, self.btn_max, self.btn_close]
        for btn in ls_btn:
            btn.setFixedWidth(45)
        hbl_btn.addWidget(self.btn_min)
        hbl_btn.addWidget(self.btn_max)
        hbl_btn.addWidget(self.btn_close)
        frame.setLayout(hbl_btn)

        self.btn_close.clicked.connect(self.close)
        self.btn_max.clicked.connect(self.onMaxRestore)  # 窗口最大化，最小化
        self.btn_min.clicked.connect(self.showMinimized)

    def onMaxRestore(self):
        if self.isMaximized():
            self.showNormal()
            self.btn_max.setToolTip("最大化")
            self.setSVG(":images/max.svg", self.btn_max)
        else:
            self.showMaximized()
            self.btn_max.setToolTip("向下还原")
            self.setSVG(":images/restore.svg", self.btn_max)

    @staticmethod
    def setSVG(path: str, p_wdg: QPushButton):
        style = """
            background-image: url({});
            background-position: center;
            background-repeat: no-repeat;
        """.format(path)
        p_wdg.setStyleSheet(style)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    main = MainWidgets()
    main.show()
    sys.exit(app.exec())
